<template>
  <div
    class="common-item"
    :class="{ selected, editing, 'editing-active': editingActive }"
    @click.stop="$emit('on-outer-click')"
    ref="item"
  >
    <div class="content-line-container">
      <div
        class="common-item-container"
        @click.stop="e => $emit('on-inner-click', e)"
        @dblclick.stop="$emit('on-inner-dblclick')"
      >
        <div class="head">
          <div
            class="checkbox"
            :class="{ checked: item.done }"
            @click.stop="onToggleDone"
            @dblclick.stop=""
          ></div>
          <template v-if="!editing">
            <div
              :class="item && item.title ? 'title' : 'title empty'"
              :title="title"
            >
              {{ title }}
              <span v-if="item.note && !editing" style="margin-left:4px"
                >📄</span
              >
            </div>
          </template>
          <template v-else>
            <input
              type="text"
              v-model="newTitle"
              ref="title"
              placeholder="新建待办事项"
              @keydown="kbd.handler"
              :title="newTitle"
              :disabled="!editing"
            />
          </template>
        </div>
        <t-slide-transition>
          <div v-show="editing" class="note">
            <div class="container">
              <t-textarea
                v-model="newNote"
                placeholder="备注"
                @keydown="kbd2.handler"
              ></t-textarea>
            </div>
          </div>
        </t-slide-transition>
      </div>
    </div>
  </div>
</template>
<script>
import { KeyBinding, KeyCode, KeyMod } from "@winwin/keybinding.js";
/**
 * How to manage user interaction with single direction data flow?
 *
 *                        [ user interaction ]
 *                                 ↕
 *                              data(sub) ───> mutation
 *        [ user interaction ]     │              │
 *                 ↕ ───────────> prop            ↓
 *   ┌─> props ─> data ─> mutation ─> store(apollo/vuex) ─┐
 *   └────────────────────────────────────────────────────┘
 */
import COMMON_ITEM_TOGGLE_DONE from "../graphql/CommonItemToggleDone.gql";
import COMMON_ITEM_UPDATE from "../graphql/CommonItemUpdate.gql";
import DATA_ALL from "../graphql/DataAll.gql";
import TSlideTransition from "./ui/TSlideTransition";
import TTextarea from "./ui/TTextarea";
import uniqueId from "lodash/uniqueId";
export default {
  name: "CommonItem",
  components: {
    TSlideTransition,
    TTextarea
  },
  props: {
    item: {
      type: Object,
      requied: true
    },
    selected: {
      type: Boolean,
      default: false
    },
    editing: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      newTitle: this.item.title,
      newNote: this.item.note,
      newDone: false,
      editingActive: false,
      kbd: new KeyBinding("commonitem.title." + uniqueId()),
      kbd2: new KeyBinding("commonitem.note." + uniqueId())
    };
  },
  watch: {
    ["item.title"](v) {
      this.newTitle = v;
    },
    ["item.note"](v) {
      this.newNote = v;
    },
    done(v) {
      this.newDone = v;
    },
    editing(v) {
      this.editingActive = true;
      if (v) this.newTitle = this.item.title;
      this.$nextTick(() => {
        if (v) this.$refs.title.focus();
      });
    }
  },
  computed: {
    title() {
      const item = this.item;
      return item && item.title ? item.title : "新建待办事项";
    }
  },
  methods: {
    save() {
      const newTitle = this.newTitle;
      const newNote = this.newNote;
      const newDone = this.newDone;
      this.$apollo
        .mutate({
          mutation: COMMON_ITEM_UPDATE,
          variables: {
            item: {
              id: this.item.id,
              title: newTitle,
              note: newNote,
              done: newDone
            }
          },
          update: (store, { data: { updateCommonItem } }) => {
            const data = store.readQuery({ query: DATA_ALL });
            const index = data.commonItems.findIndex(
              o => o.id === this.item.id
            );
            if (index !== -1) {
              data.commonItems[index].title = updateCommonItem.commonItem.title;
              data.commonItems[index].note = updateCommonItem.commonItem.note;
              data.commonItems[index].done = updateCommonItem.commonItem.done;
            }
            store.writeQuery({ query: DATA_ALL, data });
          }
        })
        .then(() => {
          this.$emit("on-close");
        });
    },
    onToggleDone() {
      this.newDone = !this.newDone;
      this.$apollo.mutate({
        mutation: COMMON_ITEM_TOGGLE_DONE,
        variables: {
          item: {
            id: this.item.id,
            done: this.newDone
          }
        },
        update: (store, { data: { updateCommonItem } }) => {
          const data = store.readQuery({ query: DATA_ALL });
          const index = data.commonItems.findIndex(o => o.id === this.item.id);
          if (index !== -1) {
            data.commonItems[index].done = updateCommonItem.commonItem.done;
          }
          store.writeQuery({ query: DATA_ALL, data });
        }
      });
    }
  },
  mounted() {
    this.first = true;
    if (this.editing) this.editingActive = true;
    this.$refs.item.addEventListener("transitionend", () => {
      if (this.$refs.item) this.editingActive = false;
    });
    this.kbd.stop([
      KeyCode.Backspace,
      KeyCode.Delete,
      KeyCode.UpArrow,
      KeyCode.DownArrow
    ]);
    this.kbd2.stop([
      KeyCode.Backspace,
      KeyCode.Delete,
      KeyCode.UpArrow,
      KeyCode.DownArrow
    ]);
    this.kbd.register(
      "save.when.title.1",
      KeyCode.Enter,
      () => {
        if (this.editing) this.save();
      },
      { stop: true }
    );
    this.kbd.register(
      "save.when.title.2",
      KeyMod.CtrlCmd | KeyCode.Enter,
      () => {
        if (this.editing) this.save();
      },
      { stop: true }
    );
    this.kbd.register(
      "toggledone",
      KeyMod.CtrlCmd | KeyCode.KEY_D,
      () => {
        this.onToggleDone();
      },
      { prevent: true }
    );
    this.kbd2.register(
      "save.when.note",
      KeyMod.CtrlCmd | KeyCode.Enter,
      () => {
        // console.log(KeyBinding._map);
        if (this.editing) this.save();
      },
      { stop: true }
    );
    this.kbd2.register(
      "toggledone",
      KeyMod.Alt | KeyCode.KEY_D,
      () => {
        this.onToggleDone();
      },
      { prevent: true }
    );
  },
  beforeDestroy() {
    this.kbd.dispose();
    this.kbd2.dispose();
  }
};
</script>
<style lang="less">
.common-item.editing-active {
  transition: all ease-out 200ms;
  .common-item-container {
    transition: all ease-out 200ms;
    .note {
      transition: all ease-out 200ms;
    }
  }
}
.common-item.editing {
  padding-top: 30px;
  padding-bottom: 30px;
  .common-item-container {
    padding-left: 14px;
    padding-right: 14px;
    padding-top: 14px;
    padding-bottom: 40px;
    margin-left: -18px;
    background-color: #ffffff;
    box-shadow: #00000022 0 0 3px 1px;
  }
}
.common-item.selected .common-item-container {
  background-color: #cee2fc;
}
.common-item-container {
  padding: 4px;
  border-radius: 3px;
  font-size: 14px;
  margin-left: -8px;
  display: flex;
  flex-direction: column;
  .checkbox {
    flex: 0 0 20px;
    margin-right: 4px;
    position: relative;
    &::before {
      content: "";
      position: absolute;
      width: 10px;
      height: 10px;
      border: 1px solid #999999;
      border-radius: 3px;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }
    &.checked::before {
      background-color: #999999;
    }
    &.checked::after {
      content: "";
      position: absolute;
      width: 6px;
      height: 3px;
      border: 2px solid #ffffff;
      border-radius: 1px;
      border-right-width: 0;
      border-top-width: 0;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -70%) rotate(-45deg);
    }
  }
  .head {
    flex: 1;
    height: 20px;
    display: flex;
    margin-right: 8px;
    .title {
      flex: 1;
      width: 0;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
      &.empty {
        color: #999999;
      }
    }
    input {
      border: none;
      outline: none;
      background-color: transparent;
      flex: 1;
      font-size: 14px;
      padding: 0;
      font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
    }
  }
  .note {
    overflow: hidden;
  }
  .note .container {
    margin-top: 8px;
    margin-left: 24px;
    margin-right: 24px;
    overflow-y: auto;

    span {
      color: #afb3b7;
    }

    textarea {
      min-height: 60px;
      font-size: 14px;
      resize: none;
      width: 100%;
      font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
      outline: none;
      padding: 0;
      border: none;
      background-color: transparent;
      &::-webkit-scrollbar {
        display: none;
      }
    }
  }
}
</style>
